home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / PASCAL / FPKPAS65.ZIP / SRCRTLDO.ZIP / SOURCE / RTL / DOS / SYSTEM.INC < prev    next >
Encoding:
Text File  |  1996-07-23  |  45.6 KB  |  1,724 lines

  1. {****************************************************************************
  2.  
  3.                        Copyright (c) 1993,1995 by
  4.                     Florian Klämpfl & Michael Spiegel
  5.  
  6.  ****************************************************************************}
  7.  
  8.  
  9. { betriebssystemunabhaengige Implementationen der Unit System }
  10.  
  11.     {$I SET.INC}
  12.  
  13.     type       
  14.        textbuf = array[0..127] of char;
  15.  
  16.        textrec = record
  17.           handle : word;
  18.           mode : word;
  19.           bufsize : word;
  20.           { private : word; PRIVATE ist Schluesselwort }
  21.           _private : word;
  22.           bufpos : word;
  23.           bufend : word;
  24.           bufptr : ^textbuf;
  25.           openfunc : pointer;
  26.           inoutfunc : pointer;
  27.           flushfunc : pointer;
  28.           closefunc : pointer;
  29.           userdata : array[1..16] of byte;
  30.           name : string[79];
  31.           buffer : textbuf;
  32.        end;
  33.  
  34.     { folgende Routinen nicht direkt aufrufen }
  35.  
  36.     procedure help_constructor;
  37.  
  38.       begin
  39.          asm
  40. .globl HELP_CONSTRUCTOR_NE
  41. HELP_CONSTRUCTOR_NE:
  42.             { Einsprung ohne Prolog, da wir ESP vom Constructor brauchen }
  43.             { Stack (relativ zu %ebp):
  44.                 12 Self
  45.                 8 VMT-Adresse
  46.                 4 Hauptprogramm-Addr
  47.                 0 %ebp
  48.             }
  49.             { Self initialisieren? }
  50.             orl %esi,%esi
  51.             jne LHC_4
  52.             { Speicher anfordern, aber erst Register retten }
  53.             { Hilfsvariable }
  54.             subl $4,%esp
  55.             movl %esp,%esi
  56.             { Register retten }
  57.             pushal
  58.             { Speichergröße }
  59.             movl 8(%ebp),%eax
  60.             pushl (%eax)
  61.             pushl %esi
  62.             call GETMEM
  63.             popal
  64.             { Speicherbereich nach %esi }
  65.             movl (%esi),%esi
  66.             addl $4,%esp
  67.             { falls kein Speicher vorhanden fail() }
  68.             orl %esi,%esi
  69.             jz LHC_5
  70.             { Self für Konstruktor initialisieren }
  71.             movl %esi,12(%ebp)
  72.          LHC_4:
  73.             { VMT-Adresse in Instanz eintragen... }
  74.             movl 8(%ebp),%eax
  75.             { ...falls eine übergeben wurde }
  76.             orl %eax,%eax
  77.             jnz LHC_7
  78.             { falls der Konstruktor nichts macht, darf das Zero-Flag }
  79.             { nicht gesetzt sein, da sonst fail() "aufgerufen" wird }
  80.             incl %eax
  81.             ret
  82.          LHC_7:
  83.             movl %eax,(%esi)
  84.          LHC_5:
  85.             ret
  86.          end;
  87.       end;
  88.  
  89.     procedure help_constructor_ex;
  90.  
  91.       begin
  92.          asm
  93. .globl HELP_CONSTRUCTOR_E
  94. HELP_CONSTRUCTOR_E:
  95.             { Stack (relativ zu %ebp):
  96.                 16 Self
  97.                 12 VMT-Adresse
  98.                 8 Exceptionsaddr
  99.                 4 Haup>tprogramm-Addr
  100.                 0 %ebp
  101.             }
  102.             { Self initialisieren? }
  103.             orl %esi,%esi
  104.             jne LHC_1
  105.             { Speicher anfordern, aber erst Register retten }
  106.             { Hilfsvariable }
  107.             subl $4,%esp
  108.             movl %esp,%esi
  109.             pushal
  110.             { Speichergröße }
  111.             movl 12(%ebp),%eax
  112.             pushl (%eax)
  113.             pushl %esi
  114.             call GETMEM
  115.             popal
  116.             { Speicherbereich nach %esi }
  117.             movl (%esi),%esi
  118.             addl $4,%esp
  119.             { Self für Konstruktor initialisieren }
  120.             movl %esi,16(%ebp)
  121.          LHC_1:
  122.             { VMT-Adresse in Instanz eintragen... }
  123.             movl 12(%ebp),%eax
  124.             { ...falls eine übergeben wurde }
  125.             orl %eax,%eax
  126.             jnz LHC_8
  127.             { falls der Konstruktor nichts macht, darf das Zero-Flag }
  128.             { nicht gesetzt sein, da sonst fail() "aufgerufen" wird }
  129.             incl %eax
  130.             ret $4
  131.          LHC_8:
  132.             movl %eax,(%esi)
  133.          LHC_6:
  134.             ret $4
  135.          end;
  136.       end;
  137.  
  138.     procedure help_fail;
  139.  
  140.       begin
  141.          asm
  142.          end;
  143.       end;
  144.  
  145.     procedure help_destructor;
  146.  
  147.       begin
  148.          asm
  149.             { Stack (relativ zu %ebp):
  150.                 12 Self
  151.                 8 VMT-Adresse
  152.                 4 Hauptprogramm-Addr
  153.                 0 %ebp
  154.             }
  155. .globl HELP_DESTRUCTOR_NE
  156. HELP_DESTRUCTOR_NE:
  157.             { temporäre Variable }
  158.             subl $4,%esp
  159.             movl %esp,%edi
  160.             pushal
  161.             { muß das Objekt gelöscht werden ? }
  162.             movl 8(%ebp),%eax
  163.             orl %eax,%eax
  164.             jz LHD_3
  165.             { ja, dann Größe aus SELF! laden }
  166.             movl 12(%ebp),%eax
  167.             { VMT-Zeiger (aus Self) nach %ebx }
  168.             movl (%eax),%ebx
  169.             { und Größe auf den Stack }
  170.             pushl (%ebx)
  171.             { SELF }
  172.             movl %eax,(%edi)
  173.             pushl %edi
  174.             call FREEMEM
  175.          LHD_3:
  176.             popal
  177.             addl $4,%esp
  178.             ret
  179.          end;
  180.       end;
  181.  
  182.     procedure help_destructor_e;
  183.  
  184.       begin
  185.          asm
  186.             { Stack (relativ zu %ebp):
  187.                 16 Self
  188.                 12 VMT-Adresse
  189.                 8 Exceptionsaddr
  190.                 4 Hauptprogramm-Addr
  191.                 0 %ebp
  192.             }
  193. .globl HELP_DESTRUCTOR_E
  194. HELP_DESTRUCTOR_E:
  195.             { temporäre Variable }
  196.             subl $4,%esp
  197.             movl %esp,%edi
  198.             pushal
  199.             { muß das Objekt gelöscht werden ? }
  200.             movl 12(%ebp),%eax
  201.             orl %eax,%eax
  202.             jz LHD_1
  203.             { ja, dann Größe aus SELF! laden }
  204.             movl 16(%ebp),%eax
  205.             { VMT-Zeiger (aus Self) nach %ebx }
  206.             movl (%eax),%ebx
  207.             { und Größe auf den Stack }
  208.             pushl (%ebx)
  209.             { SELF }
  210.             movl %eax,(%edi)
  211.             pushl %edi
  212.             call FREEMEM
  213.          LHD_1:
  214.             popal
  215.             addl $4,%esp
  216.             ret
  217.          end;
  218.       end;
  219.  
  220.     procedure runerror(w : word);
  221.  
  222.       function get_addr : longint;
  223.       
  224.         begin
  225.            asm
  226.               movl 16(%ebp),%eax
  227.            end ['EAX'];
  228.         end;
  229.  
  230.       begin
  231.          writeln('Laufzeitfehler ',w,' bei ',get_addr);
  232.          halt(1);
  233.       end;
  234.  
  235.     procedure io1(addr : longint);[public,alias: 'IOCHECK'];
  236.     
  237.       var
  238.          l : longint;
  239.  
  240.       begin
  241.          { da IOCHECK direkt aufgerufen wird und später der Optimierer }
  242.          { vielleicht auch global Register zuweist               }
  243.          asm
  244.             pushal
  245.          end;
  246.          l:=ioresult;
  247.          if l<>0 then
  248.            begin
  249.               writeln('IO-Error ',l,' at ',addr);
  250.               halt(1);
  251.            end;
  252.          asm
  253.             popal
  254.          end;
  255.       end;
  256.  
  257.     procedure re_overflow;[public,alias: 'RE_OVERFLOW'];
  258.  
  259.       var
  260.          addr : longint;
  261.  
  262.       begin
  263.          { Überlauf war kurz vor der Returnadresse }
  264.          asm
  265.             movl 4(%ebp),%edi
  266.             movl %edi,-4(%ebp)
  267.          end;
  268.          writeln('Überlauf bei ',addr);
  269.          halt(1);
  270.       end;
  271.  
  272. {$E-}
  273.  
  274.     { kopiert Strings }
  275.     { Darf nie direkt aufgerufen werden, da  *** nicht ***  mit }
  276.     { einer Exceptionadresse auf dem Stack gerechnet wird }
  277.     { außerdem werden Parameter von links nach rechts erwartet!! }
  278.     procedure strcopy(dstr,sstr : pointer;len : longint);[public,alias: 'STRCOPY'];
  279.     
  280.       begin
  281.          asm
  282.             cld
  283.             movl 16(%ebp),%edi    // Parameter laden
  284.             movl 12(%ebp),%esi
  285.             movl 8(%ebp),%ecx
  286.             lodsb        // Laenge von Quelle laden
  287.             cmpb %cl,%al
  288.             jbe LM4
  289.             movb %cl,%al    // wenn laenger als max. Laenge des Ziel,
  290.                         // dann Quelle abschneiden
  291.          LM4:
  292.             movzbl %al,%eax
  293.             mov %eax,%ecx
  294.             stosb        // Länge speichern
  295.             shrl $2,%ecx     // Erst dwordweise kopieren
  296.             rep
  297.             movsl
  298.             movb %al,%cl     // ...und nun die restlichen Bytes
  299.             andb $3,%cl
  300.             rep
  301.             movsb
  302.             leave        // eigenes Return, wegen anderem Stackframe
  303.             ret $12
  304.          end;
  305.       end;
  306. {$E-}
  307.     { verknüpft Strings }
  308.     { Darf nie direkt aufgerufen werden, da  *** nicht ***  mit }
  309.     { einer Exceptionadresse auf dem Stack gerechnet wird }
  310.     { haengt s2 an s1 an }
  311.     { außerdem werden Parameter von links nach rechts erwartet!! }
  312.     procedure strconcat(s1,s2 : pointer);[public,alias: 'STRCONCAT'];
  313.  
  314.       begin
  315.          asm
  316.         movl 12(%ebp),%edi    // Laenge des ersten Strings nach ECX
  317.         movb (%edi),%cl
  318.         movzbl %cl,%ecx
  319.         movl 12(%ebp),%edi  // Startadresse fuer den zweiten String
  320.                     // berechnen
  321.         lea 1(%edi,%ecx),%edi
  322.         negl %ecx        // Restplatz berechnen
  323.         addl $0xff,%ecx
  324.         movl 8(%ebp),%esi    // Laenge des zweiten Strings nach AL
  325.         lodsb
  326.             cmpb %cl,%al
  327.             jbe LM5
  328.             movb %cl,%al    // falls zu lang, dann abschneiden
  329.      LM5:
  330.         movb %al,%cl
  331.         movl 12(%ebp),%ebx
  332.         addb %cl,(%ebx)     // Resultatlaenge schreiben
  333.         movzbl %cl,%ecx
  334.             movl %ecx,%eax     // Laenge retten
  335.             shrl $2,%ecx     // Erst dwordweise kopieren
  336.             cld
  337.             rep
  338.             movsl
  339.             movl %al,%cl     // ...und nun die restlichen Bytes
  340.             andb $3,%cl
  341.             rep
  342.             movsb
  343.             leave        // eigenes Return, wegen anderem Stackframe
  344.             ret $8
  345.          end ['EAX','EBX','ECX','EDI'];
  346.       end;
  347.  
  348.     { vergleicht Strings (Flags sind danach gesetzt }
  349.     { Darf nie direkt aufgerufen werden, da  *** nicht ***  mit }
  350.     { einer Exceptionadresse auf dem Stack gerechnet wird }
  351.     { außerdem werden Parameter von links nach rechts erwartet!! }
  352. {$E-}
  353.     procedure strcmp(dstr,sstr : pointer);[public,alias: 'STRCMP'];
  354.     
  355.       begin
  356.          asm
  357.             movl 12(%ebp),%esi
  358.             movl 8(%ebp),%edi
  359.             cld
  360.             lodsb        // Laenge des ersten Strings nach AL
  361.             movb (%edi),%ah    // Laenge des zweiten Strings nach AH
  362.             incl %edi
  363.             movb %al,%cl    // den kuerzeren String berechnen
  364.             cmpb %ah,%cl
  365.             jbe LSTRCONCAT1
  366.             movb %ah,%cl
  367.         LSTRCONCAT1:
  368.             orb %cl,%cl        // Laenge gleich 0 ?
  369.             jz LSTRCONCAT2
  370.             movzbl %cl,%ecx
  371.             rep            // Stringvergleich
  372.             cmpsb
  373.             jne LSTRCONCAT3    // Ende erreicht ?
  374.         LSTRCONCAT2:
  375.             cmpb %ah,%al    // dann Laengenvergleich
  376.         LSTRCONCAT3:
  377.             leave        // eigenes Return, wegen anderem Stackframe
  378.             ret $8
  379.          end;
  380.       end;
  381.  
  382.     function strpas(p : pchar) : string;
  383.  
  384.       begin
  385.          asm
  386.             cld
  387.             movl 12(%ebp),%edi
  388.             movl %edi,%esi               // Quelle
  389.             movl $0xffffffff,%ecx        // nach Ende suchen
  390.             xorb %al,%al
  391.             repne
  392.             scasb
  393.             notl %ecx
  394.             decl %ecx
  395.             movl 8(%ebp),%edi          //  Ziel neu laden
  396.             movb %cl,%al
  397.             stosb
  398.             rep
  399.             movsb
  400.          end ['ECX','EAX','ESI','EDI'];
  401.       end;
  402.  
  403.     function strlen(p : pchar) : longint;
  404.  
  405.       begin
  406.          asm
  407.             cld
  408.             movl 8(%ebp),%edi
  409.             movl $0xffffffff,%ecx
  410.             xorb %al,%al
  411.             repne
  412.             scasb
  413.             movl $0xfffffffe,%eax
  414.             subl %ecx,%eax
  415.             leave
  416.             ret $4
  417.          end ['EDI','ECX','EAX'];
  418.       end;
  419.  
  420.     procedure move(var source;var dest;count : longint);
  421.  
  422.       { count : EBP+16 }
  423.  
  424.       var
  425.          sp,dp : pointer;
  426.  
  427.       { sp : EBP-4 }
  428.       { dp : EBP-8 }
  429.  
  430.       begin
  431.          if count=0 then
  432.            exit;
  433.          sp:=@source;
  434.          dp:=@dest;
  435.          if sp>dp then
  436.            asm
  437.               cld
  438.               movl 16(%ebp),%ecx
  439.               movl -4(%ebp),%esi
  440.               movl -8(%ebp),%edi
  441.               movl %ecx,%eax
  442.               shrl $2,%ecx
  443.               rep
  444.               movsl
  445.               movl %eax,%ecx
  446.               andl $3,%ecx
  447.               rep
  448.               movsb
  449.            end ['ESI','EDI','ECX','EAX']
  450.          else if sp<dp then
  451.            { vorsichtshalber rückwärts kopieren: }
  452.            asm
  453.               std
  454.               movl 16(%ebp),%ecx
  455.               movl -4(%ebp),%esi
  456.               movl -8(%ebp),%edi
  457.               addl %ecx,%esi
  458.               addl %ecx,%edi
  459.               movl %ecx,%eax
  460.               andl $3,%ecx
  461.               orl %ecx,%ecx
  462.               jz LMOVE1
  463.               { ESI und EDI müssen erst richtig berechnet werden }
  464.               decl %esi
  465.               decl %edi
  466.               rep
  467.               movsb
  468.               incl %esi
  469.               incl %edi
  470.            LMOVE1:
  471.               subl $4,%esi
  472.               subl $4,%edi
  473.               movl %eax,%ecx
  474.               shrl $2,%ecx
  475.               rep
  476.               movsl
  477.               cld
  478.            end ['ESI','EDI','ECX'];
  479.       end;
  480.  
  481.     procedure fillchar(var x;count : longint;value : byte);
  482.  
  483.       begin
  484.          asm
  485.             movl 8(%ebp),%edi
  486.             movl 12(%ebp),%ecx
  487.             movb 16(%ebp),%dl
  488.             // EAX mit 4fachem Byte füllen:
  489.             movb %dl,%dh
  490.             movw %dx,%ax
  491.             shll $16,%eax
  492.             movw %dx,%ax
  493.             movl %ecx,%edx
  494.             shrl $2,%ecx
  495.             cld
  496.             rep
  497.             stosl
  498.             movl %edx,%ecx
  499.             andl $3,%ecx
  500.             rep
  501.             stosb
  502.          end ['EAX','ECX','EDX','EDI'];
  503.       end;
  504.  
  505.     procedure fillchar(var x;count : longint;value : char);
  506.  
  507.       begin
  508.          fillchar(x,count,byte(value));
  509.       end;
  510.  
  511.     procedure fillword(var x;count : longint;value : word);
  512.  
  513.       begin
  514.          asm
  515.             movl 8(%ebp),%edi
  516.             movl 12(%ebp),%ecx
  517.             movw 16(%ebp),%dx
  518.             // EAX mit 4fachem Byte füllen:
  519.             movw %dx,%ax
  520.             shll $16,%eax
  521.             movw %dx,%ax
  522.             movl %ecx,%edx
  523.             shrl $1,%ecx
  524.             cld
  525.             rep
  526.             stosl
  527.             movl %edx,%ecx
  528.             andl $1,%ecx
  529.             rep
  530.             stosw
  531.          end ['EAX','ECX','EDX','EDI'];
  532.       end;
  533.  
  534.     {$I INNR.INC}
  535.  
  536.     function lo(w : word) : byte;[INTERNPROC: in_lo_word];
  537.     function hi(w : word) : byte;[INTERNPROC: in_hi_word];
  538.     function lo(i : integer) : byte;[INTERNPROC: in_lo_word];
  539.     function hi(i : integer) : byte;[INTERNPROC: in_hi_word];
  540.  
  541.     function lo(l : longint) : word;[INTERNPROC: in_lo_long];
  542.     function hi(l : longint) : word;[INTERNPROC: in_hi_long];
  543.  
  544.     function ord(c : char) : byte;[INTERNPROC: in_ord_char];
  545.  
  546.     {!!!!!! nicht besonders schnell, aber einfach }
  547.     function ord(b : boolean) : byte;
  548.     
  549.       begin
  550.          asm
  551.             movb 8(%ebp),%al
  552.             leave
  553.             ret
  554.          end;
  555.       end;
  556.       
  557.     function chr(b : byte) : char;[INTERNPROC: in_chr_byte];
  558.  
  559.     function length(s : string) : byte;[INTERNPROC: in_length_string];
  560.  
  561.     procedure inc(var i : longint);[INTERNPROC: in_inc_dword];
  562.     procedure inc(var i : integer);[INTERNPROC: in_inc_word];
  563.     procedure inc(var i : word);[INTERNPROC: in_inc_word];
  564.     procedure inc(var i : shortint);[INTERNPROC: in_inc_byte];
  565.     procedure inc(var i : byte);[INTERNPROC: in_inc_byte];
  566.     procedure dec(var i : longint);[INTERNPROC: in_dec_dword];
  567.     procedure dec(var i : integer);[INTERNPROC: in_dec_word];
  568.     procedure dec(var i : word);[INTERNPROC: in_dec_word];
  569.     procedure dec(var i : shortint);[INTERNPROC: in_dec_byte];
  570.     procedure dec(var i : byte);[INTERNPROC: in_dec_byte];
  571.  
  572.     procedure inc(var i : longint;a : longint);
  573.  
  574.       begin
  575.          i:=i+a;
  576.       end;
  577.  
  578.     procedure dec(var i : longint;a : longint);
  579.  
  580.       begin
  581.          i:=i-a;
  582.       end;
  583.  
  584.     procedure dec(var i : word;a : longint);
  585.  
  586.       begin
  587.          i:=i-a;
  588.       end;
  589.  
  590.     procedure inc(var i : word;a : longint);
  591.  
  592.       begin
  593.          i:=i+a;
  594.       end;
  595.  
  596.     procedure dec(var i : integer;a : longint);
  597.  
  598.       begin
  599.          i:=i-a;
  600.       end;
  601.  
  602.     procedure inc(var i : integer;a : longint);
  603.  
  604.       begin
  605.          i:=i+a;
  606.       end;
  607.  
  608.     procedure dec(var i : byte;a : longint);
  609.  
  610.       begin
  611.          i:=i-a;
  612.       end;
  613.  
  614.     procedure inc(var i : byte;a : longint);
  615.  
  616.       begin
  617.          i:=i+a;
  618.       end;
  619.  
  620.     procedure dec(var i : shortint;a : longint);
  621.  
  622.       begin
  623.          i:=i-a;
  624.       end;
  625.  
  626.     procedure inc(var i : shortint;a : longint);
  627.  
  628.       begin
  629.          i:=i+a;
  630.       end;
  631.  
  632.     function abs(l : longint) : longint;
  633.  
  634.       begin
  635.          asm
  636.             movl 8(%ebp),%eax
  637.             orl %eax,%eax
  638.             jns LMABS1
  639.             negl %eax
  640.          LMABS1:
  641.             leave
  642.             ret $4
  643.          end ['EAX'];
  644.       end;
  645.  
  646.     function odd(l : longint) : boolean;
  647.  
  648.       begin
  649.         asm
  650.            movl 8(%ebp),%eax
  651.            andl $1,%eax
  652.            setnz %al
  653.            leave
  654.            ret $4
  655.         end ['EAX'];
  656.       end;
  657.  
  658.     function sqr(l : longint) : longint;
  659.  
  660.       begin
  661.          asm
  662.             movl 8(%ebp),%eax
  663.             imull %eax,%eax
  664.             leave
  665.             ret $4
  666.          end ['EAX'];
  667.       end;
  668.  
  669.     {$I MATH.INC}
  670.  
  671.     procedure str(l : longint;var s : string);
  672.  
  673.       var
  674.          buffer : array[0..11] of byte;
  675.  
  676.       begin
  677.          { Workaround: }
  678.          if l=$80000000 then
  679.            begin
  680.               s:='-2147483648';
  681.               exit;
  682.            end;
  683.          asm
  684.             movl 8(%ebp),%eax        // Integer laden
  685.             movl 12(%ebp),%edi        // Stringadresse laden
  686.             xorl %ecx,%ecx        // Stringlaenge=0
  687.             xorl %ebx,%ebx        // Bufferlaenge=0
  688.             movl $0x0a,%esi        // 10 als Konstante zum Dividieren laden
  689.             testl $0x80000000,%eax    // vorzeichenbehaftet
  690.             jz LM2
  691.             neg %eax
  692.             movb $0x2d,1(%edi)      // '-' in String kopieren
  693.             incl %ecx
  694.          LM2:
  695.             cdql
  696.             idivl %esi,%eax
  697.             addb $0x30,%dl        // Rest in ASCII umrechnen
  698.             movb %dl,-12(%ebp,%ebx)
  699.             incl %ebx
  700.             cmpl $0,%eax
  701.             jnz LM2
  702.                             // String umkopieren
  703.          LM3:
  704.             movb -13(%ebp,%ebx),%al     // -13 da EBX erst später
  705.                                 // dekremiert wird (spart Vergleich)
  706.             movb %al,1(%edi,%ecx)
  707.             incl %ecx
  708.             decl %ebx
  709.             jnz LM3
  710.             movb %cl,(%edi)        // Stringlänge kopieren
  711.          end;
  712.       end;
  713.       
  714.    procedure str(i : integer;var s : string);
  715.    
  716.      begin
  717.         str(longint(i),s);
  718.      end;
  719.         
  720.    procedure str(si : shortint;var s : string);
  721.    
  722.      begin
  723.         str(longint(si),s);
  724.      end;
  725.      
  726.    procedure str(b : byte;var s : string);
  727.    
  728.      begin
  729.         str(longint(b),s);
  730.      end;
  731.      
  732.    procedure str(w : word;var s : string);
  733.    
  734.      begin
  735.         str(longint(w),s);
  736.      end;
  737.  
  738.    { weder besonders genau noch schnell, aber solide und leicht verständlich }
  739.  
  740.     procedure val(const s : string;var d : double;var code : word);
  741.  
  742.       var
  743.          { faster on a pentium }
  744.          esign,sign : double;
  745.  
  746.          i : longint;
  747.          exponent : longint;
  748.          flags : byte;
  749.          hd : double;
  750.  
  751.       begin
  752.          d:=0;
  753.          code:=1;
  754.          exponent:=0;
  755.          esign:=1;
  756.          flags:=0;
  757.          sign:=1;
  758.          while (s[code]=' ') or (s[code]=#9) do
  759.            inc(code);
  760.          if s[code]='+' then
  761.            inc(code)
  762.          else if s[code]='-' then
  763.            begin
  764.               sign:=-1.0;
  765.               inc(code);
  766.            end;
  767.          while (s[code]>='0') and (s[code]<='9') and (length(s)>=code) do
  768.            begin
  769.               { Vorkomma gelesen }
  770.               flags:=flags or 1;
  771.               d:=d*10;
  772.               d:=d+(ord(s[code])-ord('0'));
  773.               inc(code);
  774.            end;
  775.          { Kommastellen ? }
  776.          if (s[code]='.') and (length(s)>=code) then
  777.            begin
  778.               hd:=0.1;
  779.               inc(code);
  780.               { nach einem "Komma" muß eine Ziffer folgen }
  781.               if not((s[code]>='0') and (s[code]<='9')) or (length(s)<code) then
  782.                 begin
  783.                    d:=0.0;
  784.                    exit;
  785.                 end;
  786.               while (s[code]>='0') and (s[code]<='9') and (length(s)>=code) do
  787.                 begin
  788.                    { Nackkomma gelesen }
  789.                    flags:=flags or 2;
  790.                    d:=d+hd*(ord(s[code])-ord('0'));
  791.                    hd:=hd/10.0;
  792.                    inc(code);
  793.                 end;
  794.            end;
  795.          { weder Vorkomma- noch Nachkommastellen, dann abbrechen }
  796.          if flags=0 then
  797.            begin
  798.               d:=0.0;
  799.               exit;
  800.            end;
  801.          { Exponent ? }
  802.          if (upcase(s[code])='E') and (length(s)>=code) then
  803.            begin
  804.               inc(code);
  805.               if s[code]='+' then
  806.                 inc(code)
  807.               else if s[code]='-' then
  808.                 begin
  809.                    esign:=-1;
  810.                    inc(code);
  811.                 end;
  812.               if not((s[code]>='0') and (s[code]<='9')) or (length(s)<code) then
  813.                 begin
  814.                    d:=0.0;
  815.                    exit;
  816.                 end;
  817.               while (s[code]>='0') and (s[code]<='9') and (length(s)>=code) do
  818.                 begin
  819.                    exponent:=exponent*10;
  820.                    exponent:=exponent+ord(s[code])-ord('0');
  821.                    inc(code);
  822.                 end;
  823.            end;
  824.          { nun noch Exponent einrechnen }
  825.          if esign>0 then
  826.            for i:=1 to exponent do
  827.              d:=d*10
  828.          else
  829.            for i:=1 to exponent do
  830.              d:=d/10;
  831.          { nicht alle Zeichen gelesen ? }
  832.          if length(s)>=code then
  833.            begin
  834.               d:=0.0;
  835.               exit;
  836.            end;
  837.          { evalute sign }
  838.          d:=d*sign;
  839.          { success ! }
  840.          code:=0;
  841.       end;
  842.  
  843.     procedure val(const s : string;var b : byte);
  844.  
  845.       var
  846.          l : longint;
  847.  
  848.       begin
  849.          val(s,l);
  850.          b:=l;
  851.       end;
  852.  
  853.     procedure val(const s : string;var b : byte;var code : word);
  854.  
  855.       var
  856.          l : longint;
  857.  
  858.       begin
  859.          val(s,l,code);
  860.          b:=l;
  861.       end;
  862.  
  863.     procedure val(const s : string;var v : longint;var code : word);
  864.  
  865.       var
  866.          i : byte;
  867.          u : byte;
  868.          negativ : boolean;
  869.  
  870.       begin
  871.          negativ := false;
  872.          code := 1;
  873.          u := 0;
  874.          v := 0;
  875.          case s[1] of
  876.             '-' : begin
  877.                      negativ := true;
  878.                      code := 2;
  879.                   end;
  880.             '+' : code := 2;
  881.          end;
  882.          case s[code] of
  883.             '$' : begin
  884.                      i := 16;
  885.                      inc (code);
  886.                      while s[code] = #48 do inc (code);
  887.                      if ord (s[0]) - code > 7 then
  888.                         begin
  889.                            inc (code,8);
  890.                            exit;
  891.                         end;
  892.                   end;
  893.             '%' : begin
  894.                      i := 2;
  895.                      inc (code);
  896.                   end
  897.             else i := 10;
  898.          end;
  899.          u := 0;
  900.          v := 0;
  901.          while chr (code) <= s[0] do
  902.            begin
  903.               case s[code] of
  904.                  #48..#57  : u := ord (s[code]) - 48;
  905.                  #65..#70  : u := ord (s[code]) - 55;
  906.                  #97..#104 : u := ord (s[code]) - 87
  907.                  else u := 16;
  908.               end;
  909.               if (2147483647 - v*i < u) and ((i = 10) or (i = 2)) then u := 16;
  910.               if u >= i then
  911.                 begin
  912.                    v := 0;
  913.                    exit;
  914.                 end;
  915.                v := (v*i + u);
  916.                inc (code);
  917.             end;
  918.          code := 0;
  919.          if negativ then v := 0-v;
  920.       end;
  921.  
  922.     procedure val(const s : string;var v : longint);
  923.  
  924.      var
  925.         code : word;
  926.  
  927.      begin
  928.         val (s,v,code);
  929.      end;
  930.  
  931.     {$I real2str.inc}
  932.  
  933.     procedure str(d : double;var s : string);
  934.  
  935.       begin
  936.          str_real(-1,d,s);
  937.       end;
  938.       
  939.     var
  940.        randseed : longint;
  941.  
  942.     function random(l : longint) : longint;
  943.  
  944.       begin
  945.          randseed:=randseed*134775813+1;
  946.          random:=abs(randseed mod l);
  947.       end;
  948.  
  949.     { nicht direkt aufrufen, Aufruf wird am Ende des Hauptprogramms }
  950.     { vom Compiler generiert                        }
  951.  
  952.     procedure do_exit;[public,alias: '__EXIT'];
  953.  
  954.       begin
  955.          while exitproc<>nil do
  956.            begin
  957. {$ifdef DOS}
  958.               asm
  959.                  movl U_SYSTEM_EXITPROC,%eax
  960.                  call %eax
  961.               end;
  962. {$endif}
  963. {$ifdef OS2}
  964.               asm
  965.                  movl U_SYSOS2_EXITPROC,%eax
  966.                  call %eax
  967.               end;
  968. {$endif}
  969. {$ifdef LINUX}
  970.               asm
  971.                  movl U_SYSLINUX_EXITPROC,%eax
  972.                  call %eax
  973.               end;
  974. {$endif}
  975.            end;
  976.      end;
  977.  
  978. {****************************************************************************
  979.                     Unterprogramme zu Dateibearbeitung
  980.  ****************************************************************************}
  981.         
  982.     type
  983.        filerec = record
  984.           handle : word;
  985.           mode : word;
  986.           recsize : word;
  987.           _private : array[1..26] of byte;
  988.           userdata : array[1..16] of byte;
  989.           name : string[79];
  990.        end;
  991.  
  992.     procedure doswrite(h,addr,len : longint);forward;
  993.     function dosread(h,addr,len : longint) : longint;forward;
  994.  
  995.     procedure fileinoutfunc(var f : textrec);
  996.  
  997.       begin
  998.          if f.mode=fmoutput then
  999.            begin
  1000.               doswrite(f.handle,longint(f.bufptr),f.bufpos);
  1001.            end
  1002.          else if f.mode=fminput then
  1003.            begin
  1004.               f.bufend:=dosread(f.handle,longint(f.bufptr),f.bufsize);
  1005.            end
  1006.          else halt(100);
  1007.          f.bufpos:=0;
  1008.       end;
  1009.  
  1010.     type
  1011.         dateifunc = procedure(var t : textrec);
  1012.  
  1013.     procedure fileopenfunc(var f : textrec);forward;
  1014.  
  1015.     procedure assign(var t : text;const s : string);
  1016.  
  1017.       begin
  1018.          textrec(t).mode:=fmclosed;
  1019.          textrec(t).bufsize:=128;
  1020.          textrec(t).bufpos:=0;
  1021.          textrec(t).bufend:=0;
  1022.          textrec(t).bufptr:=@textrec(t).buffer;
  1023.          textrec(t).name:=s;
  1024.          textrec(t).openfunc:=@fileopenfunc;
  1025.       end;
  1026.  
  1027.     procedure assign(var f : file;const name : string);
  1028.  
  1029.       begin
  1030.          filerec(f).name:=name;
  1031.          filerec(f).mode:=fmclosed;
  1032.       end;
  1033.  
  1034.     procedure rewrite(var t : text);[iocheck];
  1035.  
  1036.       begin
  1037.          textrec(t).mode:=fmoutput;
  1038.          dateifunc(textrec(t).openfunc)(textrec(t));
  1039.       end;
  1040.  
  1041.     procedure reset(var t : text);[iocheck];
  1042.  
  1043.       begin
  1044.          textrec(t).mode:=fminput;
  1045.          dateifunc(textrec(t).openfunc)(textrec(t));
  1046.       end;
  1047.  
  1048.     procedure w(len : longint;var f : textrec;var s : string);[public,alias: 'WRITE_TEXT_STRING'];
  1049.  
  1050.       var
  1051.          hbytes,pos,copybytes : longint;
  1052.          hs : string;
  1053.  
  1054.       begin
  1055.          if f.mode<>fmoutput then
  1056.            exit;
  1057.          copybytes:=length(s);
  1058.          
  1059.          if len>copybytes then
  1060.            begin
  1061.               hs:=space(len-copybytes);
  1062.               w(0,f,hs);
  1063.           end;        
  1064.          pos:=1;
  1065.          hbytes:=f.bufsize-f.bufpos;
  1066.  
  1067.          { wenn überhaupt kein Platz, dann ein flush durchführen }
  1068.          if hbytes=0 then
  1069.            dateifunc(f.flushfunc)(f);
  1070.          
  1071.          while copybytes>hbytes do
  1072.            begin
  1073.               move(s[pos],f.buffer[f.bufpos],hbytes);
  1074.               f.bufpos:=f.bufpos+hbytes;
  1075.               dec(copybytes,hbytes);
  1076.               inc(pos,hbytes);
  1077.               dateifunc(f.inoutfunc)(f);
  1078.               hbytes:=f.bufsize-f.bufpos;
  1079.            end;
  1080.          move(s[pos],f.buffer[f.bufpos],copybytes);
  1081.          f.bufpos:=f.bufpos+copybytes;  
  1082.       end;
  1083.  
  1084.     type
  1085.        array00 = array[0..0] of char;
  1086.  
  1087.     procedure w(len : longint;var f : textrec;const p : array00);[public,alias: 'WRITE_TEXT_PCHAR_AS_ARRAY'];
  1088.  
  1089.       var
  1090.          hbytes,pos,copybytes : longint;
  1091.          hs : string;
  1092.  
  1093.       begin
  1094.          if f.mode<>fmoutput then
  1095.            exit;
  1096.          copybytes:=strlen(p);
  1097.          if len>copybytes then
  1098.            begin
  1099.               hs:=space(len-copybytes);
  1100.               w(0,f,hs);
  1101.            end;
  1102.          pos:=0;
  1103.          hbytes:=f.bufsize-f.bufpos;
  1104.  
  1105.          { wenn überhaupt kein Platz, dann ein flush durchführen }
  1106.          if hbytes=0 then
  1107.            dateifunc(f.flushfunc)(f);
  1108.  
  1109.          while copybytes>hbytes do
  1110.            begin
  1111.               move(p[pos],f.buffer[f.bufpos],hbytes);
  1112.               f.bufpos:=f.bufpos+hbytes;
  1113.               dec(copybytes,hbytes);
  1114.               inc(pos,hbytes);
  1115.               dateifunc(f.inoutfunc)(f);
  1116.               hbytes:=f.bufsize-f.bufpos;
  1117.            end;
  1118.          move(p[pos],f.buffer[f.bufpos],copybytes);
  1119.          f.bufpos:=f.bufpos+copybytes;
  1120.       end;
  1121.  
  1122.     procedure wa(len : longint;var f : textrec;p : pchar);[public,alias: 'WRITE_TEXT_PCHAR_AS_POINTER'];
  1123.  
  1124.       begin
  1125.          w(len,f,p);
  1126.       end;
  1127.  
  1128.     procedure f1;[public,alias: 'FLUSH_STDOUT'];
  1129.  
  1130.       begin
  1131.          { da FLUSH_STDOUT direkt aufgerufen wird und später der Optimierer }
  1132.          { vielleicht auch global Register zuweist                }
  1133.          asm
  1134.             pushal
  1135.          end;
  1136.          dateifunc(textrec(output).flushfunc)(textrec(output));
  1137.          asm
  1138.             popal
  1139.          end;
  1140.       end;
  1141.  
  1142.     procedure flush(var t : text);[iocheck];
  1143.  
  1144.       begin
  1145.          if textrec(t).mode<>fmoutput then
  1146.            exit;
  1147.          dateifunc(textrec(t).flushfunc)(textrec(t));
  1148.       end;
  1149.  
  1150.     procedure doserase(p : pchar);forward;
  1151.     procedure dosrename(p1,p2 : pchar);forward;
  1152.  
  1153.     procedure erase(var t : text);[iocheck];
  1154.  
  1155.       var
  1156.          b : array[0..79] of char;
  1157.  
  1158.       begin
  1159.          if textrec(t).mode=fmclosed then
  1160.            begin
  1161.               move(textrec(t).name[1],b,length(textrec(t).name));
  1162.               b[length(textrec(t).name)]:=#0;
  1163.               doserase(b);
  1164.            end;
  1165.       end;
  1166.  
  1167.     procedure erase(var f : file);[iocheck];
  1168.  
  1169.       var
  1170.          b : array[0..79] of char;
  1171.  
  1172.       begin
  1173.          if filerec(f).mode=fmclosed then
  1174.            begin
  1175.               move(filerec(f).name[1],b,length(filerec(f).name));
  1176.               b[length(filerec(f).name)]:=#0;
  1177.               doserase(b);
  1178.            end;
  1179.       end;
  1180.  
  1181.     procedure rename(var f : file;const s : string);[iocheck];
  1182.  
  1183.       var
  1184.          b1,b2 : array[0..79] of char;
  1185.  
  1186.       begin
  1187.          if filerec(f).mode=fmclosed then
  1188.            begin
  1189.               move(filerec(f).name[1],b1,length(filerec(f).name));
  1190.               b1[length(filerec(f).name)]:=#0;
  1191.               move(s[1],b2,length(s));
  1192.               b2[length(s)]:=#0;
  1193.               dosrename(b1,b2);
  1194.               filerec(f).name:=s;
  1195.            end;
  1196.       end;
  1197.  
  1198.     procedure rename(var t : text;const s : string);[iocheck];
  1199.  
  1200.       var
  1201.          b1,b2 : array[0..79] of char;
  1202.  
  1203.       begin
  1204.          if textrec(t).mode=fmclosed then
  1205.            begin
  1206.               move(textrec(t).name[1],b1,length(textrec(t).name));
  1207.               b1[length(textrec(t).name)]:=#0;
  1208.               move(s[1],b2,length(s));
  1209.               b2[length(s)]:=#0;
  1210.               dosrename(b1,b2);
  1211.               textrec(t).name:=s;
  1212.            end;
  1213.       end;
  1214.  
  1215.     procedure w(len : longint;var t : textrec;l : longint);[public,alias: 'WRITE_TEXT_LONGINT'];
  1216.  
  1217.       var
  1218.          s : string;
  1219.  
  1220.       begin
  1221.          str(l,s);
  1222.          w(len,t,s);
  1223.       end;
  1224.       
  1225.     procedure w(fixkomma,len : longint;var t : textrec;r : real);[public,alias: 'WRITE_TEXT_REAL'];
  1226.  
  1227.       var
  1228.          s : string;
  1229.  
  1230.       begin
  1231.          str_real(fixkomma,r,s);
  1232.          w(len,t,s);
  1233.       end;
  1234.  
  1235.     { heißt wc, damit der Compiler keinen rekursiven Aufruf erzeugt }
  1236.  
  1237.     procedure wc(len : longint;var t : textrec;c : char);[public,alias: 'WRITE_TEXT_CHAR'];
  1238.     
  1239.       var
  1240.          hs : string;
  1241.  
  1242.       begin
  1243.          if t.mode<>fmoutput then
  1244.            exit;
  1245.            
  1246.          if len>1 then
  1247.            begin
  1248.               hs:=space(len-1);
  1249.               w(0,t,hs);
  1250.            end;
  1251.            
  1252.          if t.bufpos+1>=t.bufsize then
  1253.            dateifunc(t.flushfunc)(t);
  1254.          t.buffer[t.bufpos]:=c;
  1255.          inc(t.bufpos);
  1256.       end;
  1257.  
  1258.     procedure r(var f : textrec);[public,alias: 'READLN_TEXT'];
  1259.  
  1260.       begin
  1261.          { Datei muß zum Lesen geöffnet sein }
  1262.          if f.mode<>fminput then
  1263.            exit;
  1264.          { Noch Zeichen im Buffer? ansonsten laden }
  1265.          if f.bufpos>=f.bufend then
  1266.            dateifunc(f.inoutfunc)(f);
  1267.          while f.buffer[f.bufpos]<>#10 do
  1268.            begin
  1269.               { trotz Laden nichts im Buffer ? }
  1270.               if f.bufpos>=f.bufend then
  1271.                 { dann vergiss' s }
  1272.                 exit;
  1273.               inc(f.bufpos);
  1274.               if f.bufpos>=f.bufend then
  1275.                 dateifunc(f.inoutfunc)(f);
  1276.            end;
  1277.          inc(f.bufpos);
  1278.       end;
  1279.  
  1280.     procedure r(var f : textrec;var s : string);[public,alias: 'READ_TEXT_STRING'];
  1281.  
  1282.       begin
  1283.          { the file must be opened for input }
  1284.          if f.mode<>fminput then
  1285.            exit;
  1286.          { delete the string }
  1287.          s:='';
  1288.          { Noch Zeichen im Buffer? ansonsten Laden }
  1289.          if f.bufpos>=f.bufend then
  1290.            dateifunc(f.inoutfunc)(f);
  1291.  
  1292.          while f.buffer[f.bufpos]<>#10 do
  1293.            begin
  1294.               { if no chars in the buffer, then forget this }
  1295.               if f.bufpos>=f.bufend then
  1296.                 exit;
  1297.               if f.buffer[f.bufpos]<>#13 then
  1298.                 s:=s+f.buffer[f.bufpos];
  1299.               inc(f.bufpos);
  1300.               if f.bufpos>=f.bufend then
  1301.                 dateifunc(f.inoutfunc)(f);
  1302.            end;
  1303.       end;
  1304.  
  1305.     procedure r(var f : textrec;var l : longint);[public,alias: 'READ_TEXT_LONGINT'];
  1306.  
  1307.       var
  1308.          hs : string;
  1309.          code : word;
  1310.  
  1311.       label
  1312.          ready;
  1313.  
  1314.       begin
  1315.          if f.mode<>fminput then
  1316.            exit;
  1317.          { del the number }
  1318.          l:=0;
  1319.          { clear the string }
  1320.          hs:='';
  1321.          { Noch Zeichen im Buffer? ansonsten Laden }
  1322.          if f.bufpos>=f.bufend then
  1323.            dateifunc(f.inoutfunc)(f);
  1324.          { ignore spaces }
  1325.          while (f.buffer[f.bufpos]=#13) or
  1326.                (f.buffer[f.bufpos]=#10) or
  1327.                (f.buffer[f.bufpos]=#9) or
  1328.                (f.buffer[f.bufpos]=' ') do
  1329.            begin
  1330.               { if no chars in the buffer, then forget this }
  1331.               if f.bufpos>=f.bufend then
  1332.                 exit;
  1333.               inc(f.bufpos);
  1334.               if f.bufpos>=f.bufend then
  1335.                 dateifunc(f.inoutfunc)(f);
  1336.            end;
  1337.          { read the sign }
  1338.          if (f.buffer[f.bufpos]='-') or
  1339.             (f.buffer[f.bufpos]='+') then
  1340.            begin
  1341.               { if no chars in the buffer, then forget this }
  1342.               if f.bufpos>=f.bufend then
  1343.                 goto ready;
  1344.  
  1345.               hs:=hs+f.buffer[f.bufpos];
  1346.               inc(f.bufpos);
  1347.               if f.bufpos>=f.bufend then
  1348.                 dateifunc(f.inoutfunc)(f);
  1349.            end;
  1350.          while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1351.            (ord(f.buffer[f.bufpos])<=ord('9')) do
  1352.            begin
  1353.               { if no chars in the buffer, then forget this }
  1354.               if f.bufpos>=f.bufend then
  1355.                 goto ready;
  1356.  
  1357.               hs:=hs+f.buffer[f.bufpos];
  1358.               inc(f.bufpos);
  1359.               if f.bufpos>=f.bufend then
  1360.                 dateifunc(f.inoutfunc)(f);
  1361.            end;
  1362.       ready:
  1363.          val(hs,l,code);
  1364.          if code<>0 then
  1365.            runerror(106);
  1366.       end;
  1367.  
  1368.     procedure r(var f : textrec;var c : char);[public,alias: 'READ_TEXT_CHAR'];
  1369.  
  1370.       var
  1371.          hs : string;
  1372.          code : word;
  1373.  
  1374.       begin
  1375.          c:=#0;
  1376.  
  1377.          { the file must be opened for input }
  1378.          if f.mode<>fminput then
  1379.            exit;
  1380.  
  1381.          { maybe reload }
  1382.          if f.bufpos>=f.bufend then
  1383.            dateifunc(f.inoutfunc)(f);
  1384.  
  1385.          if f.bufpos>=f.bufend then
  1386.            c:=#26
  1387.          else c:=f.buffer[f.bufpos];
  1388.  
  1389.          inc(f.bufpos);
  1390.       end;
  1391.  
  1392.     procedure r(var f : textrec;var d : double);[public,alias: 'READ_TEXT_REAL'];
  1393.  
  1394.       var
  1395.          hs : string;
  1396.          code : word;
  1397.  
  1398.       label
  1399.          ready;
  1400.  
  1401.       begin
  1402.          { f... long code }
  1403.          if f.mode<>fminput then
  1404.            exit;
  1405.          { del the number }
  1406.          d:=0.0;
  1407.          { clear the string }
  1408.          hs:='';
  1409.  
  1410.          { maybe reload }
  1411.          if f.bufpos>=f.bufend then
  1412.            dateifunc(f.inoutfunc)(f);
  1413.  
  1414.          { ignore spaces }
  1415.          while (f.buffer[f.bufpos]=#13) or
  1416.                (f.buffer[f.bufpos]=#10) or
  1417.                (f.buffer[f.bufpos]=#9) or
  1418.                (f.buffer[f.bufpos]=' ') do
  1419.            begin
  1420.               { if no chars in the buffer, then forget this }
  1421.               if f.bufpos>=f.bufend then
  1422.                 exit;
  1423.               inc(f.bufpos);
  1424.               if f.bufpos>=f.bufend then
  1425.                 dateifunc(f.inoutfunc)(f);
  1426.            end;
  1427.  
  1428.          { read the sign }
  1429.          if (f.buffer[f.bufpos]='-') or
  1430.             (f.buffer[f.bufpos]='+') then
  1431.            begin
  1432.               { if no chars in the buffer, then forget this }
  1433.               if f.bufpos>=f.bufend then
  1434.                 goto ready;
  1435.  
  1436.               hs:=hs+f.buffer[f.bufpos];
  1437.               inc(f.bufpos);
  1438.               if f.bufpos>=f.bufend then
  1439.                 dateifunc(f.inoutfunc)(f);
  1440.            end;
  1441.          while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1442.            (ord(f.buffer[f.bufpos])<=ord('9')) do
  1443.            begin
  1444.               { if no chars in the buffer, then forget this }
  1445.               if f.bufpos>=f.bufend then
  1446.                 goto ready;
  1447.  
  1448.               hs:=hs+f.buffer[f.bufpos];
  1449.               inc(f.bufpos);
  1450.               if f.bufpos>=f.bufend then
  1451.                 dateifunc(f.inoutfunc)(f);
  1452.            end;
  1453.          { comma ? }
  1454.          if (f.buffer[f.bufpos]='.') then
  1455.            begin
  1456.               { if no chars in the buffer, then forget this }
  1457.               if f.bufpos>=f.bufend then
  1458.                 goto ready;
  1459.  
  1460.               hs:=hs+'.';
  1461.               inc(f.bufpos);
  1462.               if f.bufpos>=f.bufend then
  1463.                 dateifunc(f.inoutfunc)(f);
  1464.  
  1465.               while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1466.                 (ord(f.buffer[f.bufpos])<=ord('9')) do
  1467.                 begin
  1468.                    { if no chars in the buffer, then forget this }
  1469.                    if f.bufpos>=f.bufend then
  1470.                      goto ready;
  1471.  
  1472.                    hs:=hs+f.buffer[f.bufpos];
  1473.                    inc(f.bufpos);
  1474.                    if f.bufpos>=f.bufend then
  1475.                      dateifunc(f.inoutfunc)(f);
  1476.                 end;
  1477.            end;
  1478.  
  1479.          { exponent ? }
  1480.          if (upcase(f.buffer[f.bufpos])='E') then
  1481.            begin
  1482.               { if no chars in the buffer, then forget this }
  1483.               if f.bufpos>=f.bufend then
  1484.                 goto ready;
  1485.  
  1486.               hs:=hs+'E';
  1487.               inc(f.bufpos);
  1488.               if f.bufpos>=f.bufend then
  1489.                 dateifunc(f.inoutfunc)(f);
  1490.  
  1491.               { read the sign of the exponent }
  1492.               if (f.buffer[f.bufpos]='-') or
  1493.                  (f.buffer[f.bufpos]='+') then
  1494.                 begin
  1495.                    { if no chars in the buffer, then forget this }
  1496.                    if f.bufpos>=f.bufend then
  1497.                      goto ready;
  1498.  
  1499.                    hs:=hs+f.buffer[f.bufpos];
  1500.                    inc(f.bufpos);
  1501.                    if f.bufpos>=f.bufend then
  1502.                      dateifunc(f.inoutfunc)(f);
  1503.                 end;
  1504.               while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1505.                 (ord(f.buffer[f.bufpos])<=ord('9')) do
  1506.                 begin
  1507.                    { if no chars in the buffer, then forget this }
  1508.                    if f.bufpos>=f.bufend then
  1509.                      goto ready;
  1510.  
  1511.                    hs:=hs+f.buffer[f.bufpos];
  1512.                    inc(f.bufpos);
  1513.                    if f.bufpos>=f.bufend then
  1514.                      dateifunc(f.inoutfunc)(f);
  1515.                 end;
  1516.            end;
  1517.       ready:
  1518.          val(hs,d,code);
  1519.          if code<>0 then
  1520.            runerror(106);
  1521.       end;
  1522.  
  1523.     function ioresult : word;
  1524.  
  1525.       begin
  1526.          ioresult:=inoutres;
  1527.          inoutres:=0;
  1528.       end;
  1529.  
  1530.     procedure blockread(var f : file;var buf;count : word;var result : word);[iocheck];
  1531.  
  1532.       var
  1533.          rl : longint;
  1534.  
  1535.       begin
  1536.          blockread(f,buf,count,rl);
  1537.          result:=rl;
  1538.       end;
  1539.  
  1540.     procedure w(var t : textrec);[public,alias: 'WRITELN_TEXT'];
  1541.  
  1542.       var
  1543.          hs : string;
  1544.  
  1545.       begin
  1546.          hs:=#13#10;
  1547.          w(0,t,hs);
  1548.       end;
  1549.  
  1550.     procedure close(var t : text);[public,alias: 'CLOSE_TEXT',iocheck];
  1551.  
  1552.       begin
  1553.          if (textrec(t).mode<>fmclosed) then
  1554.            begin
  1555.               dateifunc(textrec(t).flushfunc)(textrec(t));
  1556.               textrec(t).mode:=fmclosed;
  1557.               dateifunc(textrec(t).closefunc)(textrec(t));
  1558.            end;
  1559.       end;
  1560.  
  1561.     procedure initexception;[public,alias: 'INITEXCEPTION'];
  1562.  
  1563.       begin
  1564.          writeln('Exception während der Programminitialisierung aufgetreten');
  1565.          halt;
  1566.       end;
  1567.  
  1568. {****************************************************************************
  1569.                     Unterprogramme zu Stringbearbeitung
  1570.  ****************************************************************************}
  1571.  
  1572.     {$E-}
  1573.  
  1574.     function copy(const s : string;index : integer;count : byte): string;
  1575.  
  1576.        var
  1577.           i : longint;
  1578.  
  1579.        begin
  1580.           if count < 0 then count := 0;
  1581.           if index <= 0 then index := 1;
  1582.           if index <= ord(s[0]) then
  1583.             begin
  1584.                if count + index > ord(s[0]) then copy[0] := chr (ord(s[0]) - index +1)
  1585.                  else copy[0] := chr (count);
  1586.                for i := 1 to ord (s[0]) do copy[i] := s [index -1 + i];
  1587.             end
  1588.           else copy[0] := #0;
  1589.        end;
  1590.  
  1591.     procedure delete(var s : string;index : integer;count : integer);
  1592.  
  1593.        var i : longint;
  1594.  
  1595.        begin
  1596.           if index <= 0 then
  1597.             begin
  1598.                count := count + index -1;
  1599.                index := 1;
  1600.             end;
  1601.           if count <= 0 then exit;
  1602.           if ord (s[0]) >= index then
  1603.             begin
  1604.                if count + index > ord (s[0]) then count:= ord (s[0]) -index + 1;
  1605.                  for i := 0 to ord (s[0]) - (count+index) do
  1606.                    s [i+index] := s[i+count+index];
  1607.                s[0] := chr(ord (s[0]) - count);
  1608.             end;
  1609.        end;
  1610.  
  1611.     procedure insert(const source : string;var s : string;index : integer);
  1612.  
  1613.        var s3 : string;
  1614.  
  1615.        begin
  1616.           if index <= 0 then index := 1;
  1617.           s3 := copy (s, index, length(s));
  1618.           if index > length (s) then index := ord(s[0]) +1;
  1619.           s[0] := chr (index - 1);
  1620.           s := s + source + s3;
  1621.        end;
  1622.  
  1623.     function pos(const substr : string;const s : string): byte;
  1624.  
  1625.        var i : longint;
  1626.            j : byte;
  1627.            e : boolean;
  1628.  
  1629.        begin
  1630.           i := 0;
  1631.           j := 0;
  1632.           e := true;
  1633.           if substr = '' then e := false;
  1634.           while (e) and (i <= length (s) - length (substr)) do
  1635.             begin
  1636.                inc (i);
  1637.                if substr = copy (s,i,length (substr)) then
  1638.                  begin
  1639.                     j := i;
  1640.                     e := false;
  1641.                  end;
  1642.             end;
  1643.           pos := j;
  1644.        end;
  1645.  
  1646.     function upcase(c : char) : char;
  1647.  
  1648.        begin
  1649.           if (c >= #97) and (c <= #122) then c := chr(ord (c) - 32)
  1650.           else if (c >= #128) and (c <= #165) then
  1651.             case c of
  1652.                  #129 : c := #154;  {D}
  1653.                  #132 : c := #142;  {D}
  1654.                  #148 : c := #153;  {D}
  1655.                  #130 : c := #144;  {F}
  1656.                  #135 : c := #128;  {F}
  1657.                  #134 : c := #143;  {E}
  1658.                  #164 : c := #165;  {E}
  1659.             end;
  1660.           upcase := c;
  1661.        end;
  1662.  
  1663.     function upcase(const s : string) : string;
  1664.  
  1665.        var i : longint;
  1666.  
  1667.        begin
  1668.           upcase[0]:=s[0];
  1669.           for i := 1 to length (s) do 
  1670.             upcase[i] := upcase (s[i]);
  1671.        end;
  1672.  
  1673.     function lowercase(c : char) : char;
  1674.  
  1675.        begin
  1676.           if (c >= #65) and (c <= #90) then c := chr(ord (c) + 32)
  1677.           else if (c >= #128) and (c <= #165) then
  1678.             case c of
  1679.                  #154 : c := #129;  {D}
  1680.                  #142 : c := #132;  {D}
  1681.                  #153 : c := #148;  {D}
  1682.                  #144 : c := #130;  {F}
  1683.                  #128 : c := #135;  {F}
  1684.                  #143 : c := #134;  {E}
  1685.                  #165 : c := #164;  {E}
  1686.             end;
  1687.           lowercase := c;
  1688.        end;
  1689.  
  1690.     function lowercase(const s : string) : string;
  1691.  
  1692.       var i : longint;
  1693.  
  1694.       begin
  1695.          lowercase [0] := s[0];
  1696.          for i := 1 to length (s) do 
  1697.            lowercase[i] := lowercase (s[i]);
  1698.       end;
  1699.  
  1700.     function space (b : byte): string;
  1701.  
  1702.        var i : longint;
  1703.  
  1704.        begin
  1705.           space[0] := chr(b);
  1706.           for i := 1 to b do space[i] := #32;
  1707.        end;
  1708.  
  1709. { old version doesn't like this }
  1710. {$ifndef VER0_6_5}
  1711. {$ifndef VER0_6_4}
  1712.     constructor tobject.create;
  1713.  
  1714.       begin
  1715.       end;
  1716.  
  1717.     destructor tobject.free;
  1718.  
  1719.       begin
  1720.       end;
  1721.  
  1722. {$endif}
  1723. {$endif}
  1724.